package eirkdbd.lab1.fuzzyqueries;

import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import eirkdbd.lab1.data.Team;
import eirkdbd.lab1.membership.MembershipFunction;


/**
 * Represents fuzzy Query for Team Data<br>
 * Constructs fuzzy query from  Membership Function (C)
 * and List of Teams to execute query on. <br>
 * Provides execute function, which triggers query and returns results stored in sorted (by membership degrees) 
 * map with following syntax key : team , value : membership degree
 */
public class FuzzyQuery {
	
	private MembershipFunction C;
	private List<Team> teams;
	
	
	/**
	 * Creates fuzzy query
	 * @param c
	 * @param teams
	 */
	public FuzzyQuery(MembershipFunction c, List<Team> teams) {
		C = c;
		this.teams = teams;
	}



	/**
	 * Executes  fuzzy query and return appropriate results structure
	 * 
	 * @return results stored in sorted (by membership degrees) 
	 * map with following syntax key : team , value : membership degree
	 */
	public Map<Team, Double> execute(){
		Map<Team, Double> fuzzyQueryResults = new HashMap<Team, Double>();
		
		double membershipDegree;
		
		for (Team team : teams){
			membershipDegree = C.getValue(team);
			fuzzyQueryResults.put(team, membershipDegree);
		}
		
		return sortResults(fuzzyQueryResults);
	}



	/**
	 * Sorts fuzzy query results
	 * @param fuzzyQueryResults - hashMap representing bipolar query results
	 * @return  - sorted (dec) by membership degree  map(linked hash map) of bipolar query results
	 */
	private Map<Team, Double> sortResults(Map<Team, Double> fuzzyQueryResults) {
		
		List<Entry<Team, Double>> list = createSortedEntryList(fuzzyQueryResults);
		
		Map<Team, Double> sortedMap = createSortedMapFromEntryList(list);
		
		return sortedMap;
	}

	/**
	 * Create sorted entry list from map
	 * @param bipolarQueryResults
	 * @return
	 */
	private List<Entry<Team, Double>> createSortedEntryList(Map<Team, Double> bipolarQueryResults) {
		//create entry list
		List<Entry<Team, Double>> list = new LinkedList<Entry<Team, Double>>(bipolarQueryResults.entrySet());
		 
		// sort list based on comparator
		Collections.sort(list, new Comparator<Entry<Team, Double>>() {
			public int compare(Entry<Team, Double> arg0, Entry<Team, Double> arg1) {				
				return arg1.getValue().compareTo(arg0.getValue());
			}			
		});
		
		return list;
	}

	/**
	 * Creates sorted map from sorted entry list
	 * @param list
	 * @return
	 */
	private Map<Team, Double> createSortedMapFromEntryList(List<Entry<Team, Double>> list) {
		//create new map
		Map<Team, Double> sortedMap = new LinkedHashMap<Team, Double>();
		for (Iterator<Entry<Team, Double>> it = list.iterator(); it.hasNext();) {
			Map.Entry<Team, Double> entry = (Map.Entry<Team, Double>) it.next();
			sortedMap.put(entry.getKey(), entry.getValue());
		}
		return sortedMap;
	}



}
